#ifndef __SERVER_HPP__
#define __SERVER_HPP__

#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include "log.hpp"
#include <string>
#include <cstring>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <functional>
#include "Thread_Poll.hpp"
#include "Calculator.hpp"

using namespace Logspace;

const std::string defaultip = "0.0.0.0";

enum
{
    Socket_Err,
    Bind_Err,
    Listen_Err,
};

class Server
{
public:
    Server(const uint16_t &port, const std::string &ip = defaultip)
        : port_(port), ip_(ip)
    {
    }

    void Init()
    {
        // 1. 创建套接字
        // 2. 绑定
        // 3. 设置监听模式


        sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd_ < 0)
        {
            Log(Level::Fatal) << "socket failed ";
            exit(Socket_Err);
        }

        int opt = 1;
        setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &opt, sizeof(opt)); 
        // 防止偶发性的服务器无法进行立即重启

        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        char clientip[32];
        inet_aton(ip_.c_str(), &local.sin_addr);
        if (bind(sockfd_, (const struct sockaddr *)&local, sizeof(local)) < 0)
        {
            Log(Level::Fatal) << "bind failed";
            exit(Bind_Err);
        }

        if (listen(sockfd_, 10) < 0)
        {
            Log(Level::Fatal) << "listen failed";
            exit(Listen_Err);
        }
        Log(Info) << "server is running";
    }

    // void Service(int fd_)
    // {
    //     char buffer[1024];
    //     while (1)
    //     {
    //         memset(buffer , 0 ,sizeof(buffer));
    //         int n = read(fd_, buffer, sizeof(buffer) - 1);
    //         if (n > 0)
    //         {
    //             buffer[n] = 0;
    //             Task task(fd_, buffer);
    //             task();
    //             if (strcmp(buffer, "quit") == 0)
    //                 break;
    //         }
    //         else if (n == 0)
    //         {
    //             close(fd_);
    //             break;
    //         }
    //         else
    //         {
    //             Log(Error) << "read error";
    //             close(fd_);
    //             break;
    //         }
    //     }
    // }

    void Service(int fd_)
    {
        static Calculator cal;
        std::string message;
        char buffer[1024];
        while (1)
        {
            memset(buffer, 0, sizeof(buffer));
            int n = read(fd_, buffer, sizeof(buffer) - 1);
            if(n > 0)
            {
                buffer[n] = 0;
                message += buffer;
                std::string ret = cal(message);
                if(ret.size() == 0) continue;
                write(fd_ , ret.c_str() , ret.size());
            }   
        }
    }

    void Start()
    {
        // 1. 建立连接
        // 2. 读取消息
        // 3. 对消息进行处理,并返回
        using fun_t = std::function<void()>;
        std::unique_ptr<thread_poll<fun_t>> &ptp = thread_poll<fun_t>::GetInstance();
        ptp->run();
        while (1)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int fd = accept(sockfd_, (struct sockaddr *)&client, &len);
            if (fd < 0)
            {
                Log(Level::Warning) << "accept failed";
            }

            // 父进程直接将fd关闭,不允许父进程与客户端进行通信
            fun_t func = std::bind(&Server::Service, this, fd);
            ptp->push(func);
        }
    }

    // void Start()
    // {
    //     // 1. 建立连接
    //     // 2. 读取消息
    //     // 3. 对消息进行处理,并返回
    //     while (1)
    //     {
    //         struct sockaddr_in client;
    //         socklen_t len = sizeof(client);
    //         int fd = accept(sockfd_, (struct sockaddr *)&client, &len);
    //         if (fd < 0)
    //         {
    //             Log(Warning) << "accept failed";
    //         }

    //         // 使用多进程来实现
    //         pid_t id = fork();
    //         if (id < 0)
    //         {
    //             Log(Fatal) << "fork failed";
    //         }
    //         else if (id == 0)
    //         {
    //             close(sockfd_);
    //             if (fork() == 0)
    //             {
    //                 Service(fd);
    //                 exit(0);
    //             }
    //             exit(0);
    //         }

    //         // 父进程直接将fd关闭,不允许父进程与客户端进行通信
    //         close(fd);
    //         pid_t rid = waitpid(id, nullptr, 0);
    //     }
    // }

private:
    uint16_t port_;
    std::string ip_;
    int sockfd_;
};

#endif